#include <iostream>
#include "Channel.hpp"
#include "Task.hpp"
#include <vector>
#include <sys/wait.h>
using work_t = std::function<void()>;
using namespace std;

enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};

class ProcessPool
{
public:
    ProcessPool(int ProcessNum, work_t work)
        : _ProcessNum(ProcessNum), _work(work)
    {
    }
    // 1.初始化线程池
    int InitProcessPool()
    {
        for (int i = 0; i < _ProcessNum; i++)
        {
            int pipefd[2];

            int n = ::pipe(pipefd);
            if (n < 0)
            {
                return PipeError;
            }
            // 管道创建完毕
            pid_t id = fork();
            if (id < 0)
                return ForkError;
            if (id == 0)
            {
                // 子进程
                ::close(pipefd[1]);
                dup2(pipefd[0], 0);
                _work();
                exit(0);
            }

            // 父进程，1.插入到队列 2.关闭读端
            ::close(pipefd[0]); // write
            _channels.emplace_back(pipefd[1], id);
        }
        return OK;
    }
    // 2.分派任务
    void DispatcherTask()
    {
        int who = 0;
        int num = 100;
        while (num--)
        {
            int cnd = tm.SelectWork();
            // 选择子进程，负载均衡
            Channel &ch = _channels[who++]; // 选出子进程
            who %= _channels.size();
            std::cout << "##################################" << std::endl;
            std::cout << "DispatcherTask Task: " << cnd << "To" << ch.Name() << "还剩：" << num << "个任务" << std::endl;
            std::cout << "##################################" << std::endl;

            ch.Send(cnd);
            sleep(1);
        }
    }

    // 3.销毁进程池
    void Distory()
    {
        for (auto ch : _channels)
        {
            ch.Close();
        }

        for (auto ch : _channels)
        {
            pid_t rid = ::waitpid(ch.ID(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child " << rid << " wait ... success" << std::endl;
            }

        }
    }

    ~ProcessPool()
    {
    }

private:
    work_t _work;
    vector<Channel> _channels;
    int _ProcessNum;
};